/*
 * Last review by   : Yaser
 * Last review date : JUL-25-09 
 */
using System;
using System.Data;
using System.Diagnostics;
using ERP.Framework.Components.Utilities.TracingHelper;

namespace ERP.Framework.Components.LoggingHelper.ErrorLog
{
    /// <summary>
    /// Log using system events
    /// </summary>
    public class WindowsErrorLog : IErrorLog
    {
        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="WindowsErrorLog"/> class.
        /// </summary>
        /// <param name="errorLogName">Name of the error log.</param>
        public WindowsErrorLog(string errorLogName)
        {
            Source = LogName = errorLogName;
            Type = ErrorLogType.Windows;
        }

        #endregion

        #region Members

        private const string TRACING_CATEGORY = "ERP.Framework.Components.LoggingHelper.ErrorLog.WindowsErrorLog";

        /// <summary>
        /// Error id column name.
        /// </summary>
        public const string ERROR_ID = "InstanceId";
        /// <summary>
        /// Error category column name.
        /// </summary>
        public const string ERROR_CATEGORY = "Category";
        /// <summary>
        /// Entry type column name.
        /// </summary>
        public const string ERROR_ENTRY_TYPE = "EntryType";
        /// <summary>
        /// Error message column name.
        /// </summary>
        public const string ERROR_MESSAGE = "Message";
        /// <summary>
        /// Error source column name.
        /// </summary>
        public const string ERROR_SOURCE = "Source";
        /// <summary>
        /// Time generated column name.
        /// </summary>
        public const string ERROR_GENERATED_TIME = "TimeGenerated";
        /// <summary>
        /// Time written column name.
        /// </summary>
        public const string ERROR_WRITTEN_TIME = "TimeWritten";
        /// <summary>
        /// User name column name.
        /// </summary>
        public const string ERROR_USER_NAME = "UserName";
        /// <summary>
        /// Machine name column name.
        /// </summary>
        public const string ERROR_MACHINE_NAME = "MachineName";
        /// <summary>
        /// Table name.
        /// </summary>
        public const string ERROR_TABLE_NAME = "ErrorLog";

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the name of the log.
        /// </summary>
        /// <value>The name of the log.</value>
        public string LogName
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the source.
        /// </summary>
        /// <value>The source.</value>
        public string Source
        {
            get;
            set;
        }

        /// <summary>
        /// the type of logging
        /// </summary>
        /// <value></value>
        public ErrorLogType Type
        {
            get;
            private set;
        }

        #endregion

        #region Methods

        /// <summary>
        /// Add new log event
        /// </summary>
        /// <param name="error">Error to add</param>
        public void Add(Exception error)
        {
            TraceUtil.Write(TRACING_CATEGORY, "Add : Start");
            if (!EventLog.Exists(LogName))
                EventLog.CreateEventSource(Source, LogName);
            EventLog log = new EventLog(LogName);
            log.Source = Source;

            log.WriteEntry(string.Format(
                "Error Message:\n{0}\n-------------------------\n" +
                "Source:\n{1}\n-------------------------\n" +
                "Target Site:\n{2}\n-------------------------\n" +
                "Inner Exception:\n{3}\n-------------------------\n" +
                "Stack Trace:\n{4}\n-------------------------\n" +
                "Help Link:\n{5}\n-------------------------\n",
                error.Message, error.Source, error.TargetSite, error.InnerException, error.StackTrace, error.HelpLink
                ), EventLogEntryType.Error, log.Entries.Count);
            TraceUtil.Write(TRACING_CATEGORY, "Add : End");
        }

        /// <summary>
        /// Read the log file
        /// </summary>
        /// <returns></returns>
        public DataTable Read()
        {
            TraceUtil.Write(TRACING_CATEGORY, "Read : Start");
            DataTable data = null;
            if (EventLog.Exists(LogName))
            {
                data = CreateSchema();
                EventLog log = new EventLog(LogName);
                log.Source = Source;
                foreach (EventLogEntry entry in log.Entries)
                {
                    DataRow error = data.NewRow();
                    error[ERROR_ID] = entry.InstanceId;
                    error[ERROR_CATEGORY] = entry.Category;
                    error[ERROR_ENTRY_TYPE] = entry.EntryType;
                    error[ERROR_MACHINE_NAME] = entry.MachineName;
                    error[ERROR_MESSAGE] = entry.Message;
                    error[ERROR_SOURCE] = entry.Source;
                    error[ERROR_GENERATED_TIME] = entry.TimeGenerated;
                    error[ERROR_WRITTEN_TIME] = entry.TimeWritten;
                    error[ERROR_USER_NAME] = entry.UserName;
                    data.Rows.Add(error);
                }
            }
            TraceUtil.Write(TRACING_CATEGORY, "Read : End");
            return data;
        }

        /// <summary>
        /// Creates the schema.
        /// </summary>
        /// <returns></returns>
        private DataTable CreateSchema()
        {
            DataTable schema = new DataTable(ERROR_TABLE_NAME);
            schema.Columns.Add(ERROR_ID);
            schema.Columns.Add(ERROR_CATEGORY);
            schema.Columns.Add(ERROR_ENTRY_TYPE);
            schema.Columns.Add(ERROR_MACHINE_NAME);
            schema.Columns.Add(ERROR_MESSAGE);
            schema.Columns.Add(ERROR_SOURCE);
            schema.Columns.Add(ERROR_GENERATED_TIME);
            schema.Columns.Add(ERROR_WRITTEN_TIME);
            schema.Columns.Add(ERROR_USER_NAME);
            return schema;
        }

        #endregion
    }
}
